home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / CGIPERL / MACPERL / MSRCE418.HQX / Perl Source ƒ / MacPerl / MPMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-17  |  26.8 KB  |  1,296 lines

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPMain.c            -    The main event loop
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPMain.c,v $
  12. Revision 1.2  1994/05/04  02:52:40  neeri
  13. Inline Input.
  14.  
  15. Revision 1.1  1994/02/27  23:01:21  neeri
  16. Initial revision
  17.  
  18. Revision 0.9  1993/12/30  00:00:00  neeri
  19. DeferredKeys
  20.  
  21. Revision 0.8  1993/12/20  00:00:00  neeri
  22. Trying to be more subtle about cursors
  23.  
  24. Revision 0.7  1993/12/12  00:00:00  neeri
  25. SacrificialGoat
  26.  
  27. Revision 0.6  1993/10/17  00:00:00  neeri
  28. Mercutio Support
  29.  
  30. Revision 0.5  1993/08/17  00:00:00  neeri
  31. Preferences
  32.  
  33. Revision 0.4  1993/08/16  00:00:00  neeri
  34. Moved scripting to separate file
  35.  
  36. Revision 0.3  1993/07/15  00:00:00  neeri
  37. Beginning to see the light
  38.  
  39. Revision 0.2  1993/05/30  00:00:00  neeri
  40. Support Console Windows
  41.  
  42. Revision 0.1  1993/05/29  00:00:00  neeri
  43. Compiles correctly
  44.  
  45. *********************************************************************/
  46.  
  47. #include <Memory.h>
  48. #include <QuickDraw.h>
  49. #include <Types.h>
  50. #include <Menus.h>
  51. #include <Windows.h>
  52. #include <Dialogs.h>
  53. #include <Traps.h>
  54. #include <Packages.h>
  55. #include <DiskInit.h>
  56. #include <PPCToolbox.h>
  57. #include <Resources.h>
  58. #include <Editions.h>
  59. #include <Printing.h>
  60. #include <ToolUtils.h>
  61. #include <Desk.h>
  62. #include <Scrap.h>
  63. #include <OSEvents.h>
  64. #include <AppleEvents.h>
  65. #include <AEObjects.h>
  66. #include <Errors.h>
  67. #include <StandardFile.h>
  68. #include <Balloons.h>
  69. #include <String.h>
  70. #include <CType.h>
  71. #include <PLStringFuncs.h>
  72. #include <StdLib.h>
  73. #include <CursorCtl.h>
  74. #include <Script.h>
  75.  
  76. #include "MPGlobals.h"
  77. #include "MPUtils.h"
  78. #include "MPEditions.h"
  79. #include "MPAppleEvents.h"
  80. #include "MPWindow.h"
  81. #include "MPFile.h"
  82. #include "MPHelp.h"
  83. #include "MPScript.h"
  84. #include "MPUtils.h"
  85. #include "MPPreferences.h"
  86. #include "Mercutio.h"
  87. #include "MPConsole.h"
  88.  
  89. #include <MacPerl.h>
  90. #define RESOLVE_MAC_CONFLICTS
  91. #include <EXTERN.h>
  92. #include <perl.h>
  93.  
  94. #if !defined(powerc) && !defined(__powerc)
  95. #pragma segment MPMain
  96. #endif
  97.  
  98. pascal void MaintainCursor()
  99. {
  100.     Point         pt;
  101.     WindowPtr     wPtr;
  102.     GrafPtr       savePort;
  103.     DPtr          theDoc;
  104.     Boolean        inText = false;
  105.     
  106.     wPtr = FrontWindow();
  107.     if (Ours(wPtr)) {
  108.         theDoc = DPtrFromWindowPtr(wPtr);
  109.         GetPort(&savePort);
  110.         SetPort(wPtr);
  111.         GetMouse(&pt);
  112. #ifndef RUNTIME
  113.         if (gTextServicesImplemented && SetTSMCursor(pt))
  114.             return;
  115. #endif
  116.         if (theDoc->theText)
  117.             if (inText = PtInRect(pt, &(**(theDoc->theText)).viewRect))
  118.                 SetCursor(&editCursor);
  119.             else
  120.                 SetCursor(&qd.arrow);
  121.         else
  122.             SetCursor(&qd.arrow);
  123.  
  124.         if (theDoc->theText)
  125.             TEIdle(theDoc->theText);
  126.  
  127. #ifndef RUNTIME
  128.         DoHelp(wPtr, theDoc, pt, inText);
  129. #endif
  130.  
  131.         SetPort(savePort);
  132.     } else if (!wPtr)
  133.         SetCursor(&qd.arrow);
  134. }
  135.  
  136. #if !defined(powerc) && !defined(__powerc)
  137. #pragma segment MPMain
  138. #endif
  139.  
  140. FSSpec        jumpFile;
  141. WindowPtr    jumpWindow;
  142. short            jumpLine;
  143.  
  144. Boolean  SeriousFSSpec(char * name)
  145. {
  146.     CInfoPBRec    info;
  147.     
  148.     if (Path2FSSpec(name, &jumpFile))
  149.         return false;
  150.     if (FSpCatInfo(&jumpFile, &info) 
  151.      || info.dirInfo.ioFlAttrib & 0x10 
  152.      || !info.hFileInfo.ioFlLgLen
  153.     ) {
  154.         if (strchr(name, ':') || !(jumpWindow = AlreadyOpen(&jumpFile, jumpFile.name)))
  155.             return false;
  156.     } else
  157.         jumpWindow = nil;
  158.     
  159.     return true;
  160. }
  161.  
  162. #ifndef RUNTIME
  163.  
  164. Boolean    ParseJump(DPtr    theDoc)
  165. {
  166.     char        endCh;
  167.     char     endFileCh;
  168.     Boolean    result = false;
  169.     TEHandle    te     = theDoc->theText;
  170.     short        len    = (*te)->selEnd - (*te)->selStart;
  171.     char *    text;
  172.     char *   end;
  173.     char *   endFile;
  174.     Str255    jumpText;
  175.     
  176.     if (len <= 0)
  177.         goto fixupMenuItem;
  178.     
  179.     HLock((*te)->hText);
  180.     text = *(*te)->hText + (*te)->selStart;
  181.     end  = text + len;
  182.     endCh= *end;
  183.     *end = 0;
  184.  
  185. rescan:    
  186.     while (isspace(*text))
  187.         ++text;
  188.     
  189.     switch (*text) {
  190.     case 'F':
  191.     case 'f':
  192.         if (toupper(text[1]) == 'I' 
  193.          && toupper(text[2]) == 'L' 
  194.          && toupper(text[3]) == 'E'
  195.          && isspace(text[4])
  196.         ) {
  197.             /* Strip off "File" prefix */
  198.             text += 5;
  199.             
  200.             goto rescan;
  201.         } else
  202.             goto slurp;
  203.     case '\'':
  204.     case '\"':
  205.         if (endFile = strchr(text+1, *text)) {
  206.             *endFile = 0;
  207.             
  208.             if (endFile - text < 1 || !SeriousFSSpec(text+1)) {
  209.                 *endFile = *text;
  210.                 
  211.                 goto repair;
  212.             }
  213.             
  214.             *endFile = *text;
  215.             text = endFile + 1;
  216.             
  217.             break;
  218.         } 
  219.         
  220.         /* Unbalanced quote, skip & fall through */
  221.         ++text;
  222.     default:
  223. slurp:
  224.         /* Break at end of line */
  225.         if (endFile = strchr(text, '\n')) {
  226.             /* Strip trailing whitespace */
  227.             while (endFile > text && isspace(endFile[-1]))
  228.                 --endFile;
  229.                 
  230.             *endFile = 0;
  231.             
  232.             if (endFile - text < 1 || !SeriousFSSpec(text)) {
  233.                 *endFile = '\n';
  234.                 
  235.                 goto repair;
  236.             }
  237.             
  238.             *endFile = '\n';
  239.             text = endFile + 1;
  240.             
  241.             break;
  242.         } 
  243.         
  244.         if (end - text < 1 || !SeriousFSSpec(text))
  245.             goto repair;
  246.         
  247.         text = end;
  248.         break;
  249.     }
  250.     
  251.     /* Try to parse line # */
  252.     
  253.     jumpLine = 0;
  254.     
  255.     while (*text)
  256.         if (isdigit(*text)) {
  257.             while (isdigit(*text))
  258.                 jumpLine = jumpLine * 10 + *text++ - '0';
  259.             
  260.             break;
  261.         } else
  262.             ++text;
  263.     
  264.     result = true;
  265.         
  266. repair:    
  267.     *end = endCh;
  268.     HLock((*te)->hText);
  269.  
  270. fixupMenuItem:
  271.     if (result) {
  272.         jumpFile.name[jumpFile.name[0]+1] = 0;
  273.         jumpText[0] = sprintf((char *) jumpText+1, "Jump to \"%s\"", jumpFile.name+1);
  274.         if (jumpLine)
  275.             jumpText[0] += 
  276.                 sprintf((char *) jumpText+jumpText[0]+1, ", Line %d", jumpLine);
  277.         SetMenuItemText(myMenus[editM], emJumpTo, jumpText);
  278.     } else 
  279.         SetMenuItemText(myMenus[editM], emJumpTo, (StringPtr) "\pJump To╔");
  280.  
  281.     return result;    
  282. }
  283.  
  284. #endif
  285.  
  286. #if !defined(powerc) && !defined(__powerc)
  287. #pragma segment MPMain
  288. #endif
  289.  
  290. static Boolean    mRunningPerl;
  291.  
  292. pascal void MaintainMenuBar()
  293. {
  294.     if (gRunningPerl != mRunningPerl) {
  295.         if (gRunningPerl) 
  296.             DeleteMenu(perlID);
  297.         else
  298.             InsertMenu(myMenus[perlM], 0);
  299.         
  300.         mRunningPerl = gRunningPerl;
  301.         
  302.         DrawMenuBar();
  303.     }
  304. }
  305.  
  306. pascal void MaintainMenus()
  307. {
  308.     DPtr               theDoc;
  309.     WindowPtr          firstWindow;
  310.     SectHandle         currSection;
  311.     
  312.     MaintainMenuBar();
  313.     
  314.     firstWindow = FrontWindow();
  315.     if (!Ours(firstWindow)) {
  316.         EnableItem(myMenus[fileM], fmNew);
  317.         EnableItem(myMenus[fileM], fmOpen);
  318.         DisableItem(myMenus[fileM], fmClose);
  319.         DisableItem(myMenus[fileM], fmSave);
  320.         DisableItem(myMenus[fileM], fmSaveAs);
  321.         DisableItem(myMenus[fileM], fmRevert);
  322.         DisableItem(myMenus[fileM], fmPrint);
  323.         DisableItem(myMenus[fileM], fmPageSetUp);
  324.         EnableItem(myMenus[fileM], fmQuit);
  325.  
  326.         if (firstWindow) {
  327.             EnableItem(myMenus[editM], undoCommand);
  328.             EnableItem(myMenus[editM], cutCommand);
  329.             EnableItem(myMenus[editM], copyCommand);
  330.             EnableItem(myMenus[editM], pasteCommand);
  331.             EnableItem(myMenus[editM], clearCommand);
  332.         } else {
  333.             DisableItem(myMenus[editM], undoCommand);
  334.             DisableItem(myMenus[editM], cutCommand);
  335.             DisableItem(myMenus[editM], copyCommand);
  336.             DisableItem(myMenus[editM], pasteCommand);
  337.             DisableItem(myMenus[editM], clearCommand);
  338.         }
  339.         EnableItem(myMenus[editM],  emPreferences);
  340.         DisableItem(myMenus[editM], selectAllCommand);
  341.  
  342. #ifndef RUNTIME
  343.         DisableItem(myMenus[editM],  emJumpTo);
  344.         
  345.         DisableItem(myMenus[editM],  cPublisher);
  346.         DisableItem(myMenus[editM],  cSubscriber);
  347.         DisableItem(myMenus[editM],  cOptions);
  348.         DisableItem(myMenus[editM],  cBorders);
  349.  
  350.         EnableItem(myMenus[helpM], hmExplain);
  351. #endif 
  352.         
  353.         if (!mRunningPerl) {
  354.             SetItem(myMenus[perlM], pmRunFront, (StringPtr) "\pRun Front Window");
  355.             DisableItem(myMenus[perlM], pmRunFront);
  356.         }
  357.     } else {
  358.         theDoc = DPtrFromWindowPtr(firstWindow);
  359.         
  360.         if (theDoc->kind == kDocumentWindow) {
  361.             EnableItem(myMenus[editM], pasteCommand);
  362. #ifndef RUNTIME
  363.             EnableItem(myMenus[editM], cBorders);
  364. #endif
  365.             if (!mRunningPerl) {
  366.                 Str255    title;
  367.                 
  368.                 PLstrcpy(title, (StringPtr) "\pRun ");
  369.                 GetWTitle(firstWindow, title+5);
  370.                 title[0]             = title[5] + 6;
  371.                 title[5]              = '"';
  372.                 title[title[0]]    = '"';
  373.                 SetItem(myMenus[perlM], pmRunFront, title);
  374.                 EnableItem(myMenus[perlM], pmRunFront);
  375.             }
  376.         } else {
  377. #ifndef RUNTIME
  378.             DisableItem(myMenus[editM], cBorders);
  379. #endif
  380.             
  381.             if ((*theDoc->theText)->selStart < theDoc->u.cons.fence)
  382.                 DisableItem(myMenus[editM], pasteCommand);
  383.             else
  384.                 EnableItem(myMenus[editM], pasteCommand);
  385.  
  386.             if (!mRunningPerl) {
  387.                 SetItem(myMenus[perlM], pmRunFront, (StringPtr) "\pRun Front Window");
  388.                 DisableItem(myMenus[perlM], pmRunFront);
  389.             }
  390.         }
  391.         
  392.         EnableItem(myMenus[fileM], fmClose);
  393.         EnableItem(myMenus[fileM], fmSave);
  394.         EnableItem(myMenus[fileM], fmSaveAs);
  395.         EnableItem(myMenus[fileM], fmPrint);
  396.         EnableItem(myMenus[fileM], fmPageSetUp);
  397.         EnableItem(myMenus[fileM], fmQuit);
  398.  
  399.         if (theDoc->kind == kDocumentWindow && theDoc->u.reg.everSaved && theDoc->dirty)
  400.             EnableItem(myMenus[fileM], fmRevert);
  401.         else
  402.             DisableItem(myMenus[fileM], fmRevert);
  403.  
  404.         DisableItem(myMenus[editM], undoCommand);
  405.  
  406.         if (((**(theDoc->theText)).selEnd - (**(theDoc->theText)).selStart) > 0) {
  407.             EnableItem(myMenus[editM], cutCommand);
  408.             EnableItem(myMenus[editM], copyCommand);
  409.             EnableItem(myMenus[editM], clearCommand);
  410. #ifndef RUNTIME
  411.             EnableItem(myMenus[editM], cPublisher);
  412. #endif
  413.         } else {
  414.             DisableItem(myMenus[editM], cutCommand);
  415.             DisableItem(myMenus[editM], copyCommand);
  416.             DisableItem(myMenus[editM], clearCommand);
  417. #ifndef RUNTIME
  418.             DisableItem(myMenus[editM], cPublisher);
  419. #endif
  420.         }
  421.         
  422.         EnableItem(myMenus[editM],  selectAllCommand);
  423.         EnableItem(myMenus[editM],  emPreferences);
  424.  
  425. #ifndef RUNTIME
  426.         if (ParseJump(theDoc))
  427.             EnableItem(myMenus[editM],  emJumpTo);
  428.         else
  429.             DisableItem(myMenus[editM],  emJumpTo);
  430.  
  431.         currSection =
  432.             GetSection(
  433.                 (**(theDoc->theText)).selStart,
  434.                 (**(theDoc->theText)).selEnd,
  435.                 theDoc);
  436.  
  437.         if (theDoc->kind != kDocumentWindow) {
  438.             DisableItem(myMenus[editM], cPublisher);
  439.             DisableItem(myMenus[editM], cSubscriber);
  440.             DisableItem(myMenus[editM], cOptions);
  441.         } else if (currSection) {
  442.             DisableItem(myMenus[editM], cPublisher);
  443.             DisableItem(myMenus[editM], cSubscriber);
  444.             EnableItem(myMenus[editM],  cOptions);
  445.             if ((**(**currSection).fSectHandle).kind == stPublisher)
  446.                 SetItem(myMenus[editM], cOptions, (StringPtr) "\pPublisher Options╔");
  447.             else
  448.                 SetItem(myMenus[editM], cOptions, (StringPtr) "\pSubscriber Options╔");
  449.         } else {
  450.             EnableItem(myMenus[editM],  cPublisher);
  451.             EnableItem(myMenus[editM],  cSubscriber);
  452.             DisableItem(myMenus[editM], cOptions);
  453.         }
  454.         
  455.         EnableItem(myMenus[helpM], hmExplain);
  456. #endif
  457.     }
  458. }
  459.  
  460. #if !defined(powerc) && !defined(__powerc)
  461. #pragma segment MPMain
  462. #endif
  463.  
  464. pascal void SetUpCursors(void)
  465. {
  466.     CursHandle  hCurs;
  467.  
  468.     hCurs = GetCursor(1);
  469.     editCursor = **hCurs;
  470.     hCurs = GetCursor(watchCursor);
  471.     waitCursor = **hCurs;
  472. }
  473.  
  474. #if !defined(powerc) && !defined(__powerc)
  475. #pragma segment MPMain
  476. #endif
  477.  
  478. pascal void SetUpMenus(void)
  479. {
  480.     short             i;
  481.     StringHandle    str;
  482.  
  483.     myMenus[appleM] = GetMenu(appleID);
  484.     AddResMenu(myMenus[appleM], 'DRVR');
  485.     myMenus[fileM] = GetMenu(fileID);
  486.     myMenus[editM] = GetMenu(editID);
  487.     myMenus[windowM]    = GetMenu(windowID);
  488.     myMenus[perlM]    = GetMenu(perlID);
  489.  
  490. #ifndef RUNTIME
  491.     for (i = appleM; i < kLastMenu; i++)
  492.         InsertMenu(myMenus[i], 0);
  493.  
  494.     HMGetHelpMenuHandle(&myMenus[helpM]);
  495.     str = GetString(helpID);
  496.     
  497.     HLock((Handle) str);
  498.     AppendMenu(myMenus[helpM], *str);
  499.     ReleaseResource((Handle) str);
  500. #else
  501.     for (i = appleM; i <= kLastMenu; i++)
  502.         InsertMenu(myMenus[i], 0);
  503. #endif
  504.     
  505.     SetShortMenus(); /* Does a DrawMenuBar() */
  506. }
  507.  
  508. pascal void DoFile(short theItem)
  509. {
  510.     short   alertResult;
  511.     DPtr    theDoc;
  512.     FSSpec  theFSSpec;
  513.     OSErr   fileErr;
  514.     TPrint  thePSetup;
  515.  
  516.     switch (theItem){
  517.     case fmNew:
  518.         IssueAENewWindow();
  519.         break;
  520.  
  521.     case fmOpen:
  522.         if (GetFile(&theFSSpec)==noErr)
  523.             fileErr = IssueAEOpenDoc(theFSSpec);
  524.         break;
  525.  
  526.     case fmClose:
  527.         IssueCloseCommand(FrontWindow());
  528.         break;
  529.  
  530.     case fmSave:
  531.     case fmSaveAs:
  532.         theDoc = DPtrFromWindowPtr(FrontWindow());
  533.  
  534.         if (theItem==fmSaveAs || theDoc->kind != kDocumentWindow || !theDoc->u.reg.everSaved) {
  535.             fileErr = GetFileNameToSaveAs(theDoc);
  536.             if (!fileErr)
  537.                 fileErr = IssueSaveCommand(theDoc, &theDoc->theFSSpec);
  538.             else if (fileErr != userCanceledErr)    
  539.                 FileError((StringPtr) "\perror saving ", theDoc->theFileName);
  540.         } else
  541.             fileErr = IssueSaveCommand(theDoc, nil);
  542.         break;
  543.  
  544.     case fmRevert:
  545.         SetCursor(&qd.arrow);
  546.         theDoc = DPtrFromWindowPtr(FrontWindow());
  547.  
  548.         ParamText(theDoc->theFileName, (StringPtr) "", (StringPtr) "", (StringPtr) "");
  549.         alertResult = Alert(RevertAlert, nil);
  550.         switch (alertResult){
  551.             case aaSave:
  552.                 if (IssueRevertCommand(theDoc->theWindow))
  553.                     FileError((StringPtr) "\perror reverting ", theDoc->theFileName);
  554.         }
  555.         break;
  556.  
  557.     case fmPageSetUp:
  558.         theDoc = DPtrFromWindowPtr(FrontWindow());
  559.         if (DoPageSetup(theDoc)) {
  560.              thePSetup = **(theDoc->thePrintSetup);
  561.              IssuePageSetupWindow(theDoc->theWindow, thePSetup);
  562.          }
  563.         break;
  564.  
  565.     case fmPrint:
  566.         IssuePrintWindow(FrontWindow());
  567.          break;
  568.  
  569.     case fmQuit:
  570.         IssueQuitCommand();
  571.         break;
  572.     } /*of switch*/
  573. }
  574.  
  575. #if !defined(powerc) && !defined(__powerc)
  576. #pragma segment MPMain
  577. #endif
  578.  
  579. pascal void DoCommand(long mResult)
  580. {
  581.     short   theItem;
  582.     short   err;
  583.     Str255  name;
  584.     DPtr    theDocument;
  585.  
  586.     if (!mResult)
  587.         return;
  588.  
  589.     theDocument = DPtrFromWindowPtr(FrontWindow());
  590.         
  591. #ifndef RUNTIME
  592.     if (gTextServicesImplemented && TSMMenuSelect(mResult))
  593.         goto done;
  594.     if (theDocument && theDocument->tsmDoc)
  595.         FixTSMDocument(theDocument->tsmDoc);
  596. #endif
  597.  
  598.     theItem = LoWord(mResult);
  599.  
  600.     switch (HiWord(mResult)) {
  601.     case appleID:
  602.         if (theItem == aboutItem) {
  603.             DoAbout();
  604.         } else {
  605.             GetItem(myMenus[appleM], theItem, name);
  606.             err = OpenDeskAcc(name);
  607.             SetPort(FrontWindow());
  608.         }
  609.           break;
  610.  
  611.     case fileID:
  612.         DoFile(theItem);
  613.         break;
  614.  
  615.     case editID:
  616.         SystemEdit(theItem - 1);
  617.  
  618.         switch (theItem) {
  619.         case cutCommand:
  620.             IssueCutCommand(theDocument);
  621.             break;
  622.  
  623.         case copyCommand:
  624.             IssueCopyCommand(theDocument);
  625.             break;
  626.  
  627.         case pasteCommand :
  628.             IssuePasteCommand(theDocument);
  629.             break;
  630.  
  631.         case clearCommand :
  632.             IssueClearCommand(theDocument);
  633.             break;
  634.  
  635.         case selectAllCommand:
  636.             if (theDocument)
  637.                 TESetSelect(0, (**(theDocument->theText)).teLength, theDocument->theText);
  638.             break;
  639.  
  640. #ifndef RUNTIME
  641.         case cPublisher:
  642.             IssueCreatePublisher(theDocument);
  643.             break;
  644.  
  645.         case cSubscriber:
  646.             DoSubscribe(theDocument);
  647.             break;
  648.  
  649.         case cOptions:
  650.             DoSectionOptions(theDocument);
  651.             break;
  652.  
  653.         case cBorders:
  654.             IssueShowBorders(theDocument->theWindow, !theDocument->u.reg.showBorders);
  655.             break;
  656.  
  657.         case emJumpTo:
  658.             IssueJumpCommand(&jumpFile, jumpWindow, jumpLine);
  659.             break;
  660. #endif
  661.             
  662.         case emFormat:
  663.             IssueFormatCommand(theDocument);
  664.             break;
  665.             
  666.         case emPreferences:
  667.             DoPrefDialog();
  668.             break;
  669.         }     /*of switch*/
  670.  
  671.         ShowSelect(theDocument);
  672.          break;
  673.     
  674.     case windowID:
  675.         DoSelectWindow(theItem);
  676.         break;
  677.  
  678.     case perlID:
  679.         DoScriptMenu(theItem);
  680.         break;
  681.  
  682. #ifndef RUNTIME    
  683.     case kHMHelpMenuID:
  684.         Explain(theDocument);
  685.         break;
  686. #endif
  687.     }                 /*of switch*/
  688.  
  689. done:
  690.     HiliteMenu(0);
  691. }
  692.  
  693. #if !defined(powerc) && !defined(__powerc)
  694. #pragma segment MPMain
  695. #endif
  696.  
  697. pascal void DoMouseDown(EventRecord *myEvent)
  698. {
  699.     WindowPtr whichWindow;
  700.     Point     p;
  701.     Rect      dragRect;
  702.  
  703.     p = myEvent->where;
  704.     switch (FindWindow(p, &whichWindow)) {
  705.     case inDesk:
  706.         SysBeep(10);
  707.         break;
  708.  
  709.     case inGoAway:
  710.         if (Ours(whichWindow))
  711.             if (TrackGoAway(whichWindow, p))
  712.                 IssueCloseCommand(whichWindow);
  713.         break;
  714.  
  715.     case inMenuBar:
  716.         SetCursor(&qd.arrow);
  717.         SetupWindowMenu();
  718.         MaintainMenus();
  719.         DoCommand(MenuSelect(p));
  720.         HiliteMenu(0);
  721.         break;
  722.  
  723.     case inSysWindow:
  724.         SystemClick(myEvent, whichWindow);
  725.         break;
  726.  
  727.     case inDrag:
  728.         dragRect = qd.screenBits.bounds;
  729.  
  730.         if (Ours(whichWindow)) {
  731.             DragWindow(whichWindow, p, &dragRect);
  732.             /*
  733.                 As rgnBBox may be passed by address
  734.             */
  735.             dragRect = (**((WindowPeek)whichWindow)->strucRgn).rgnBBox;
  736.             /*
  737.                 The windows already there, but still tell
  738.                 the our AppleEvents core about the move in case
  739.                 they want to do anything
  740.             */
  741.             IssueMoveWindow(whichWindow, dragRect);
  742.         }
  743.           break;
  744.  
  745.     case inGrow:
  746.         SetCursor(&qd.arrow);
  747.         if (Ours(whichWindow))
  748.             MyGrowWindow(whichWindow, p);
  749.         break;
  750.  
  751.     case inZoomIn:
  752.         DoZoom(whichWindow, inZoomIn, p);
  753.         break;
  754.  
  755.     case inZoomOut:
  756.         DoZoom(whichWindow, inZoomOut, p);
  757.         break;
  758.  
  759.     case inContent:
  760.         if (whichWindow != FrontWindow())
  761.             SelectWindow(whichWindow);
  762.         else
  763.             if (Ours(whichWindow))
  764.                 DoContent(whichWindow, myEvent);
  765.         break;
  766.     }                 /*of switch*/
  767. }
  768.  
  769. #if !defined(powerc) && !defined(__powerc)
  770. #pragma segment MPMain
  771. #endif
  772.  
  773. pascal long GetSleep(void)
  774. {
  775.     long      sleep;
  776.     WindowPtr theWindow;
  777.     DPtr      theDoc;
  778.  
  779.     sleep = 30;
  780.     if (!gInBackground)
  781.         {
  782.             theWindow = FrontWindow();
  783.             if (theWindow)
  784.                 {
  785.                     theDoc = DPtrFromWindowPtr(theWindow);
  786.                     if ((**(theDoc->theText)).selStart == (**(theDoc->theText)).selEnd)
  787.                         sleep = GetCaretTime();
  788.                 }
  789.         }
  790.     return(sleep);
  791. }                     /*GetSleep*/
  792.  
  793. long FindMenuKey(EventRecord * ev)
  794. {
  795. #ifndef RUNTIME
  796.     /* Work around Help manager bug */
  797.     short    item    =    CountMItems(myMenus[helpM]);
  798.     short    key;
  799.     
  800.     GetItemCmd(myMenus[helpM], item, &key);
  801.     
  802.     if (toupper((char) key) == toupper(ev->message & charCodeMask))
  803.         return (kHMHelpMenuID << 16) | item;
  804.     else
  805. #endif
  806.     {
  807.         MaintainMenus();
  808.  
  809.         return PowerMenuKey(ev->message, ev->modifiers, myMenus[fileM]);
  810.     }
  811. }
  812.  
  813. #if !defined(powerc) && !defined(__powerc)
  814. #pragma segment MPMain
  815. #endif
  816.  
  817. typedef enum {keyOK, keyRetry, keyAbort} KeyStatus;
  818.  
  819. KeyStatus TryKey(DPtr theDoc, char theChar)
  820. {
  821.     switch (theChar) {
  822.     case 0:
  823.     case 1:
  824.     case 2:
  825.     case 4:
  826.     case 5:
  827.     case 6:
  828.     case 7:
  829.     case 10:
  830.     case 11:
  831.     case 12:
  832.     case 14:
  833.     case 15:
  834.     case 16:
  835.     case 17:
  836.     case 18:
  837.     case 19:
  838.     case 20:
  839.     case 21:
  840.     case 22:
  841.     case 23:
  842.     case 24:
  843.     case 25:
  844.     case 26:
  845.     case 27:
  846.         return keyAbort;
  847.         break;
  848.     case ETX:
  849.         theChar = CR;
  850.         
  851.         break;
  852.     default:
  853.         break;
  854.     }
  855.  
  856. #ifndef RUNTIME
  857.     {
  858.         SectHandle  currSection;
  859.         
  860.         /*
  861.             don't allow a subscriber to be changed
  862.         */
  863.         currSection =
  864.             GetSection(
  865.                 (**(theDoc->theText)).selStart,
  866.                 (**(theDoc->theText)).selEnd,
  867.                 theDoc);
  868.     
  869.         if (currSection)
  870.             if ((**(**currSection).fSectHandle).kind == stSubscriber)
  871.                 if (!KeyOKinSubscriber(theChar))
  872.                     return keyAbort;
  873.     }
  874. #endif
  875.  
  876.     if (theDoc->kind == kDocumentWindow) {
  877. #ifndef RUNTIME                    
  878.         DoTEKeySectionRecalc(theDoc, theChar);
  879. #endif
  880.     } else if (theChar == BS) {
  881.         if (AllSelected(theDoc->theText)) {
  882.             if (theDoc->u.cons.fence < 32767)
  883.                 theDoc->u.cons.fence = 0;
  884.         } else if ((*theDoc->theText)->selStart == (*theDoc->theText)->selEnd)
  885.             if ((*theDoc->theText)->selStart-1 < theDoc->u.cons.fence)
  886.                 return keyAbort;
  887.             else if ((*theDoc->theText)->selStart < theDoc->u.cons.fence)
  888.                 return keyAbort;
  889.     } else if (
  890.         (*theDoc->theText)->selStart < theDoc->u.cons.fence &&
  891.         !KeyOKinSubscriber(theChar)
  892.     ) 
  893.         return keyAbort;
  894.     else if (!theDoc->u.cons.selected)
  895.         return gRunningPerl ? keyRetry : keyAbort;
  896.  
  897. #ifndef RUNTIME                    
  898.     AddKeyToTypingBuffer(theDoc, theChar);
  899. #endif
  900.  
  901.     TEKey(theChar, theDoc->theText);
  902.     EnforceMemory(theDoc, theDoc->theText);
  903.     AdjustScrollbars(theDoc, false);
  904.     ShowSelect(theDoc);
  905.  
  906.     theDoc->dirty = true;
  907.     
  908.     return keyOK;
  909. }
  910.  
  911. #ifndef RUNTIME
  912.  
  913. #if !defined(powerc) && !defined(__powerc)
  914. #pragma segment MPMain
  915. #endif
  916.  
  917. static Boolean IntlTSMEvent(EventRecord *event)
  918. {
  919.     short oldFont;
  920.     ScriptCode keyboardScript;
  921.     
  922.     if (qd.thePort != nil)
  923.     {
  924.         oldFont = qd.thePort->txFont;
  925.         keyboardScript = GetScriptManagerVariable(smKeyScript);
  926.         if (FontToScript(oldFont) != keyboardScript)
  927.             TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
  928.     };
  929.     return TSMEvent(event);
  930. }
  931.  
  932. #endif
  933. /* Our cursor/WaitNextEvent strategy */
  934.  
  935. #define BUSY_WAIT            120
  936. #define FRONT_FREQUENCY    30
  937. #define BACK_FREQUENCY  10
  938.  
  939. static long            lastNonBusy     = 0;
  940. static long         lastWNE         = 0;
  941. static char            deferredKeys[256];
  942. static short        deferredRd        = 0;
  943. static short        deferredWr        = 0;
  944. static WindowPtr    deferredWindow    = 0;
  945. static RgnHandle    mouseRgn;
  946.  
  947. #if !defined(powerc) && !defined(__powerc)
  948. #pragma segment MPMain
  949. #endif
  950.  
  951. void HandleEvent(EventRecord * myEvent)
  952. {
  953.     char        theChar;
  954.     Boolean     activate;
  955.     Point            mouse;
  956.     WindowPtr   theWindow;
  957.     DPtr        theDoc;
  958.  
  959.     theDoc = DPtrFromWindowPtr(FrontWindow());
  960.     
  961.     switch (myEvent->what) {
  962.     case mouseDown:
  963. #ifndef RUNTIME
  964.         FlushAndRecordTypingBuffer();
  965. #endif
  966.         DoMouseDown(myEvent);
  967.         lastNonBusy = TickCount();
  968.         break;
  969.  
  970.     case keyDown:
  971.     case autoKey:
  972.         if (WeirdChar(myEvent, cmdKey, ETX) 
  973.          || WeirdChar(myEvent, controlKey, 'd')
  974.         )    {
  975.             if (theDoc && theDoc->kind != kDocumentWindow) {
  976.                 gGotEof            =    theDoc;
  977.                 theDoc->dirty     =     true;
  978.             } 
  979.             
  980.             break;
  981.         } 
  982.         
  983.         theChar = myEvent->message & charCodeMask;
  984.  
  985.         if ((myEvent->modifiers & cmdKey) == cmdKey) {
  986. #ifndef RUNTIME
  987.             FlushAndRecordTypingBuffer();
  988. #endif
  989.             DoCommand(FindMenuKey(myEvent));
  990.             HiliteMenu(0);
  991.         } else if (theDoc && theDoc->theText)
  992.             switch (TryKey(theDoc, theChar)) {
  993.             case keyOK:
  994.             case keyAbort:
  995.                 break;
  996.             case keyRetry:
  997.                 if (FrontWindow() != deferredWindow) {
  998.                     deferredRd = deferredWr;
  999.                     deferredWindow = FrontWindow();
  1000.                 }
  1001.                 deferredKeys[deferredWr] = theChar;
  1002.                 deferredWr = (deferredWr + 1) & 255;
  1003.                 break;
  1004.             }
  1005.         break;
  1006.  
  1007.     case activateEvt:
  1008.         activate = ((myEvent->modifiers & activeFlag) != 0);
  1009.         theWindow = (WindowPtr)myEvent->message;
  1010.         DoActivate(theWindow, activate);
  1011.         break;
  1012.  
  1013.     case updateEvt:
  1014.         theWindow = (WindowPtr)myEvent->message;
  1015.         DoUpdate(DPtrFromWindowPtr(theWindow), theWindow);
  1016.         break;
  1017.  
  1018.     case kHighLevelEvent:
  1019. #ifndef RUNTIME
  1020.         FlushAndRecordTypingBuffer();
  1021. #endif
  1022.         DoAppleEvent(*myEvent);
  1023.         
  1024.         if (gDelayedScript.dataHandle) {
  1025.             DoScript(&gDelayedScript, nil, 0);
  1026.             AEDisposeDesc(&gDelayedScript);
  1027.         }
  1028.         break;
  1029.  
  1030.     case kOSEvent:
  1031.         switch (myEvent->message & osEvtMessageMask) { /*high byte of message*/
  1032.         case 0x01000000:
  1033. #ifndef RUNTIME
  1034.                 FlushAndRecordTypingBuffer();
  1035. #endif
  1036.                 gInBackground = ((myEvent->message & resumeFlag) == 0);
  1037.                 if (!gInBackground)
  1038.                     InitCursor();
  1039.                 DoActivate(FrontWindow(), !gInBackground);
  1040.         }
  1041.         break;
  1042.     case diskEvt:
  1043.         if (myEvent->message & 0xFFFF0000) {
  1044.             DILoad();
  1045.             SetPt(&mouse, 120, 120);
  1046.             DIBadMount(mouse, myEvent->message);
  1047.             DIUnload();
  1048.         }
  1049.     }
  1050. }
  1051.  
  1052. pascal void MainEvent(Boolean busy)
  1053. {
  1054.     DPtr        theDoc;
  1055.     Boolean        gotEvent;
  1056.     WindowPtr   theWindow;
  1057.     long            now;
  1058.     EventRecord myEvent;
  1059.     Point            mouse;
  1060.  
  1061.     if (!gSacrificialGoat)        /* Memory trouble */
  1062.         if (gRunningPerl)            /* This script has gone too far */
  1063.             fatal("Out of memory ! Aborting script for your own good...\n");
  1064.         else                            /* We aborted it, now buy a new goat */
  1065.             if (!(gSacrificialGoat = NewHandle(SACRIFICE)))
  1066.                 exit(0);        /* Save our sorry ass. Shouldn't happen */
  1067.     
  1068.     now = TickCount();
  1069.     if (busy) {
  1070.         if (now - lastNonBusy < BUSY_WAIT)
  1071.             busy = false;
  1072.     } else
  1073.         lastNonBusy = now;
  1074.     
  1075.     MaintainMenuBar();
  1076.  
  1077.     if (busy) {
  1078.         SpinCursor(1);
  1079.         
  1080.         if (now - lastWNE < (gInBackground ? BACK_FREQUENCY : FRONT_FREQUENCY))
  1081.             return;
  1082.     } else
  1083.         MaintainCursor();
  1084.     
  1085.     lastWNE = now;    
  1086.     gGotEof = nil;
  1087.     
  1088.     if (!gRunningPerl && GetHandleSize((Handle) gWaitingScripts)) {
  1089.         AppleEvent * ev    =    (*gWaitingScripts)[0];
  1090.         AppleEvent * repl    =    (*gWaitingScripts)[1];
  1091.         
  1092.         Munger((Handle) gWaitingScripts, 0, nil, 8, (Ptr) -1, 0);
  1093.         
  1094.         AEResumeTheCurrentEvent(
  1095.             ev, repl, (AEEventHandlerUPP) kAEUseStandardDispatch, -1);
  1096.     }
  1097.     
  1098.     if ((theDoc = DPtrFromWindowPtr(FrontWindow())) && theDoc->theText) 
  1099.         while (deferredKeys[deferredRd]) {
  1100.             switch (deferredWindow != FrontWindow() ? keyAbort : TryKey(theDoc, deferredKeys[deferredRd])) {
  1101.             case keyOK:
  1102.             case keyAbort:
  1103.                 deferredKeys[deferredRd] = 0;
  1104.                 deferredRd = (deferredRd + 1) & 255;
  1105.                 continue;
  1106.             }
  1107.             break;
  1108.         }
  1109.  
  1110.     if (!(theWindow = FrontWindow()))
  1111.         GetWMgrPort(&theWindow);
  1112.         
  1113.     SetPort(theWindow);
  1114.  
  1115. #ifndef RUNTIME
  1116.     SetScriptManagerVariable(smFontForce, gSavedFontForce);
  1117. #endif
  1118.  
  1119.     if (!busy) {
  1120.         if (!mouseRgn) 
  1121.             mouseRgn    =    NewRgn();
  1122.         
  1123.         GetMouse(&mouse);
  1124.         SetRectRgn(mouseRgn, mouse.h, mouse.v, mouse.h, mouse.v);
  1125.         gotEvent = WaitNextEvent(everyEvent, &myEvent, GetSleep(), mouseRgn);
  1126.     } else 
  1127.         gotEvent = WaitNextEvent(everyEvent, &myEvent, 0, nil);
  1128.  
  1129. #ifndef RUNTIME
  1130.     // clear fontForce again so it doesn't upset our operations
  1131.     gSavedFontForce = GetScriptManagerVariable(smFontForce);
  1132.     (void) SetScriptManagerVariable(smFontForce, 0);
  1133.         
  1134.     if (gotEvent && gTextServicesImplemented && IntlTSMEvent(&myEvent))
  1135.         gotEvent = false;        // TSMTE handled it without our help
  1136. #endif
  1137.  
  1138.     if (gotEvent)
  1139.         HandleEvent(&myEvent);
  1140.         
  1141.     if (gQuitting && gRunningPerl)
  1142.         longjmp(gExitPerl, -128);
  1143. }
  1144.  
  1145. pascal long VoodooChile(Size cbNeeded)
  1146. {
  1147. #if !defined(powerc) && !defined(__powerc)
  1148.     long    oldA5 = SetCurrentA5();
  1149. #endif
  1150.     long    res;
  1151.     
  1152.     if (gSacrificialGoat && (GZSaveHnd() != gSacrificialGoat)) {
  1153.         /* Oh Memory Manager, our dark Lord. Take the blood of this animal to
  1154.            unwield thy power to crush our enemies.
  1155.             
  1156.             (Chant 7 times)
  1157.         */
  1158.         DisposeHandle(gSacrificialGoat);
  1159.         
  1160.         gSacrificialGoat     =     0;
  1161.         res                    =    SACRIFICE;
  1162.     } else
  1163.         res                     =    0;
  1164.         
  1165. #if !defined(powerc) && !defined(__powerc)
  1166.     SetA5(oldA5);
  1167. #endif
  1168.     
  1169.     return res;
  1170. }
  1171.  
  1172.  
  1173. #if USESROUTINEDESCRIPTORS
  1174. RoutineDescriptor    uVoodooChile = 
  1175.         BUILD_ROUTINE_DESCRIPTOR(uppGrowZoneProcInfo, VoodooChile);
  1176. #else
  1177. #define uVoodooChile *(GrowZoneUPP)&VoodooChile
  1178. #endif
  1179.  
  1180. #if !defined(powerc) && !defined(__powerc)
  1181. #pragma segment MPMain
  1182. #endif
  1183.  
  1184. #if defined(powerc) || defined(__powerc)
  1185. extern double MPConsoleSockets;
  1186. extern double MPPseudoSockets;
  1187. double * cs;
  1188. double * ps;
  1189. #endif
  1190.  
  1191. void main()
  1192. {
  1193.     OSErr  err;
  1194.     short  result;
  1195.  
  1196. #if defined(powerc) || defined(__powerc)
  1197.     cs = &MPConsoleSockets;
  1198.     ps = &MPPseudoSockets;
  1199. #endif
  1200.  
  1201.     InitGraf(&qd.thePort);
  1202.     InitFonts();
  1203.     FlushEvents(everyEvent, 0);
  1204.     InitWindows();
  1205.     InitMenus();
  1206.     TEInit();
  1207.     InitDialogs(nil);
  1208.     InitCursor();
  1209.  
  1210.     SetApplLimit(GetApplLimit() - 65535);    /* We need more stack */
  1211.     MaxApplZone();
  1212.     SetGrowZone(&uVoodooChile);
  1213.     SetUpCursors();
  1214.  
  1215.     /*check environment checks to see if we are running 7.0*/
  1216.     if (!CheckEnvironment()) {
  1217.         SetCursor(&qd.arrow);
  1218.         /*pose the only 7.0 alert*/
  1219.         result = Alert(302, nil);
  1220.         return;
  1221.     }
  1222.  
  1223.     gPerlPrefs.version             =     PerlPrefVersion413;
  1224.     gPerlPrefs.runFinderOpens    =    false;
  1225.     gPerlPrefs.checkType            =    false;
  1226.     gPerlPrefs.inlineInput        =     true;
  1227.     
  1228.     OpenPreferences();
  1229.     
  1230.     SetUpMenus();
  1231.  
  1232.     gWCount                = 0;
  1233.     gNewDocCount         = 0;
  1234.     gQuitting              = false;
  1235.     gFontMItem             = 0;
  1236.     gConsoleList        = nil;
  1237.     gActiveWindow        = nil;
  1238.     gAppFile                = CurResFile();
  1239.     gScriptFile            = gAppFile;
  1240.     gWaitingScripts    = (AppleEvent ***) NewHandle(0);
  1241.     gGotEof                = nil;
  1242.     gSacrificialGoat    = NewHandle(SACRIFICE);
  1243.  
  1244. #ifndef RUNTIME
  1245.     if (err = InitEditionPack()) {
  1246.         ShowError((StringPtr) "\pInitEditionPack", err);
  1247.         gQuitting = true;
  1248.     }
  1249.  
  1250.     if (err = AEObjectInit()) {
  1251.         ShowError((StringPtr) "\pAEObjectInit", err);
  1252.         gQuitting = true;
  1253.     }
  1254.  
  1255.     InitAppleEvents();
  1256.  
  1257.     if (err = PPCInit()) {
  1258.         ShowError((StringPtr) "\pPPCInit", err);
  1259.         gQuitting = true;
  1260.     }
  1261.  
  1262.     if (!(gTSMTEImplemented && !InitTSMAwareApplication())) {
  1263.         gTextServicesImplemented = false;
  1264.         gTSMTEImplemented = false;
  1265.     }
  1266.  
  1267.     gSavedFontForce = GetScriptManagerVariable(smFontForce);
  1268.     (void) SetScriptManagerVariable(smFontForce, 0);
  1269. #else
  1270.     if (gAppleEventsImplemented) {
  1271.         InitAppleEvents();
  1272.         
  1273.         if (err = PPCInit()) {
  1274.             ShowError((StringPtr) "\pPPCInit", err);
  1275.             gQuitting = true;
  1276.         }
  1277.     }
  1278. #endif
  1279.     
  1280.     if (gQuitting)
  1281.         exit(0);
  1282.         
  1283.     InitPerlEnviron();
  1284.     
  1285.     GUSISetSpin(MPConsoleSpin);
  1286.     
  1287.     for (gQuitting = DoRuntime(); !gQuitting; )
  1288.         MainEvent(false);
  1289.  
  1290. #ifndef RUNTIME        
  1291.     if (gTextServicesImplemented)
  1292.         CloseTSMAwareApplication();
  1293.     SetScriptManagerVariable(smFontForce, gSavedFontForce);
  1294. #endif
  1295. }
  1296.